from tkinter import ttk
import os
from calc_utils import convert_to_pixels, convert_from_pixels


class BatchRatioMixin:
    def update_batch_ratio_state(self, *args):
        """当批量保持比例被勾选/取消勾选时，更新宽高输入框的状态"""
        # 检查是否处于特殊模式
        is_special_mode = (self.batch_maintain_ratio.get() and
                           not self.resampling_enabled.get() and
                           self.unit_var.get() in ["cm", "inch"] and
                           self.size_enabled.get())

        if is_special_mode:
            source = None
            # 判断是否由宽度或高度输入框的trace触发
            if args:  # args 存在表示由 trace 调用
                # args[0] 是 Tkinter 变量的内部名称，如 'PY_VAR0'
                # 我们需要与 self.width_var (tk.StringVar实例) 的字符串表示比较
                var_name_str = args[0]
                if var_name_str == str(self.width_var):
                    source = "width"
                elif var_name_str == str(self.height_var):
                    source = "height"
            self._apply_special_mode_rules(source_changed=source)
            return  # 特殊模式已处理，提前返回

        # --- 非特殊模式下的逻辑 ---
        if self.batch_maintain_ratio.get() and self.size_enabled.get():
            # 常规批量模式：宽度和高度输入框只有一个可以激活
            width_str = self.width_var.get().strip()
            height_str = self.height_var.get().strip()

            source_is_width = args and args[0] == str(self.width_var)
            source_is_height = args and args[0] == str(self.height_var)

            if not width_str and not height_str:  # 两者都为空
                self.width_entry.configure(state="normal")
                self.height_entry.configure(state="normal")
            elif width_str and not height_str:  # 宽度有值，高度为空
                self.width_entry.configure(state="normal")
                self.height_entry.configure(state="disabled")
                if source_is_width: self.height_var.set("")  # 如果是宽度输入触发，清空高度
            elif height_str and not width_str:  # 高度有值，宽度为空
                self.height_entry.configure(state="normal")
                self.width_entry.configure(state="disabled")
                if source_is_height: self.width_var.set("")  # 如果是高度输入触发，清空宽度
            else:  # 两者都有值（例如，通过代码设置或快速输入）
                # 默认让宽度优先，或根据触发源决定
                if source_is_width:
                    self.width_entry.configure(state="normal")
                    self.height_entry.configure(state="disabled")
                    self.height_var.set("")
                elif source_is_height:
                    self.height_entry.configure(state="normal")
                    self.width_entry.configure(state="disabled")
                    self.width_var.set("")
                else:  # 无明确触发源，默认宽度优先
                    self.width_entry.configure(state="normal")
                    self.height_entry.configure(state="disabled")
                    self.height_var.set("")

            # DPI 输入框在常规批量模式下的状态，主要由 self.dpi_enabled 和 self.size_enabled 控制
            # 通常由 update_dpi_state 或 update_size_state 处理
            general_dpi_state = "normal" if self.dpi_enabled.get() and self.size_enabled.get() else "disabled"
            self.dpi_entry.configure(state=general_dpi_state)

        else:
            # 非特殊模式，且常规批量模式也未激活 (即 batch_maintain_ratio 为 false 或 size_enabled 为 false)
            # 此时，宽度、高度、DPI 输入框的启用状态主要取决于 self.size_enabled 和 self.dpi_enabled
            current_size_state = "normal" if self.size_enabled.get() else "disabled"
            self.width_entry.configure(state=current_size_state)
            self.height_entry.configure(state=current_size_state)

            if self.dpi_enabled.get() and self.size_enabled.get():
                self.dpi_entry.configure(state="normal")
            else:
                self.dpi_entry.configure(state="disabled")

    def on_batch_ratio_changed(self):
        """当用户点击批量保持比例复选框时触发"""
        # 检查重新采样状态
        # 如果重新采样关闭且取消勾选批量保持比例，并且保持原图比例也未勾选
        # 则自动开启重新采样，因为不重新采样模式只在保持原图比例或批量保持比例勾选时有效
        if not self.resampling_enabled.get() and not self.batch_maintain_ratio.get() and not self.maintain_ratio.get():
            self.resampling_enabled.set(True)
            messagebox.showinfo("提示",
                                "已自动开启重新采样模式。\n不重新采样模式仅在勾选'保持原图比例'或'批量保持比例'时有效。")
            # 更新重新采样状态
            self.update_resampling_state()
            return

        # 如果批量保持比例被勾选
        if self.batch_maintain_ratio.get():
            # 获取当前宽高输入框的值
            width_str = self.width_var.get().strip()
            height_str = self.height_var.get().strip()

            # 如果两个输入框都有值，只保留一个，删除另一个
            if width_str and height_str:
                # 默认保留宽度，清空高度
                self.height_var.set("")
                self.height_entry.configure(state="disabled")
                self.width_entry.configure(state="normal")
            # 如果宽度和高度都为空，保持两个输入框都是空的状态
            elif not width_str and not height_str:
                self.width_entry.configure(state="normal")
                self.height_entry.configure(state="normal")
            # 如果只有一个有值，保持当前状态

            # 添加特殊处理，确保在不重新采样时批量保持比例模式下DPI和尺寸输入互不影响
            if not self.resampling_enabled.get():
                # 重置上次修改标记和标志
                self.user_input_width = False
                self.user_input_height = False
                self.user_input_dpi = False
                if hasattr(self, 'last_modified_field'):
                    delattr(self, 'last_modified_field')
                if hasattr(self, 'last_user_input_value'):
                    delattr(self, 'last_user_input_value')

        # 调用原有的更新函数来处理状态
        self.update_batch_ratio_state()

    def process_batch_ratio(self, oriented_width, oriented_height, original_dpi, uniform_dpi):
        """处理批量保持比例的图像尺寸计算

        Args:
            oriented_width: 当前图片的宽度（像素）
            oriented_height: 当前图片的高度（像素）
            original_dpi: 当前图片的DPI
            uniform_dpi: 是否所有图片的DPI都相同

        Returns:
            tuple: (最终宽度, 最终高度, 新DPI值或None) - 计算后的新尺寸和DPI
        """
        # 计算图片的原始宽高比
        aspect_ratio = oriented_height / oriented_width

        # 获取用户输入的值
        modified_width = self.width_var.get().strip()
        modified_height = self.height_var.get().strip()
        dpi_str = self.dpi_var.get().strip()
        current_unit = self.unit_var.get()

        # 默认使用原始尺寸和DPI
        final_width = oriented_width
        final_height = oriented_height
        new_dpi = None  # 如果不需要修改DPI，则返回None

        # 处理厘米或英寸单位的情况
        if current_unit in ["cm", "inch"]:
            # DPI数值均相同时的处理
            if uniform_dpi:
                # 1. 若只修改宽/高（用户清空DPI，或DPI数值为无）
                # 按用户输入的宽或高的厘米或英寸数值按原比例各自批量修改
                # 像素尺寸不变，调整DPI
                if (modified_width or modified_height) and (not dpi_str or not self.dpi_enabled.get()):
                    try:
                        if modified_width:
                            # 用户修改了宽度（厘米或英寸），计算新DPI
                            physical_width = float(modified_width)
                            # 将物理尺寸转换为英寸
                            if current_unit == "cm":
                                physical_width_inch = physical_width / 2.54
                            else:  # current_unit == "inch"
                                physical_width_inch = physical_width
                            # 计算新DPI = 像素宽度 / 物理宽度（英寸）
                            new_dpi = oriented_width / physical_width_inch
                        elif modified_height:
                            # 用户修改了高度（厘米或英寸），计算新DPI
                            physical_height = float(modified_height)
                            # 将物理尺寸转换为英寸
                            if current_unit == "cm":
                                physical_height_inch = physical_height / 2.54
                            else:  # current_unit == "inch"
                                physical_height_inch = physical_height
                            # 计算新DPI = 像素高度 / 物理高度（英寸）
                            new_dpi = oriented_height / physical_height_inch
                    except ValueError:
                        pass

                # 2. 若只修改DPI，则批量修改DPI，每张图的像素尺寸不变
                elif self.dpi_enabled.get() and dpi_str and not modified_width and not modified_height:
                    try:
                        # 直接使用用户输入的DPI值
                        new_dpi = float(dpi_str)
                    except ValueError:
                        pass

                # 3. 若都修改，按输入的DPI和宽或者高批量原比例计算
                elif self.dpi_enabled.get() and dpi_str and (modified_width or modified_height):
                    try:
                        new_dpi = float(dpi_str)
                        if modified_width:
                            # 按输入的DPI和宽度计算新的像素尺寸
                            physical_width = float(modified_width)
                            target_width = self.convert_to_pixels(physical_width, current_unit, new_dpi)
                            target_height = target_width * aspect_ratio
                            final_width = int(round(target_width))
                            final_height = int(round(target_height))
                        else:
                            # 按输入的DPI和高度计算新的像素尺寸
                            physical_height = float(modified_height)
                            target_height = self.convert_to_pixels(physical_height, current_unit, new_dpi)
                            target_width = target_height / aspect_ratio
                            final_width = int(round(target_width))
                            final_height = int(round(target_height))
                    except ValueError:
                        pass

            # DPI数值均不相同时的处理
            else:
                # 1. 此时如果只修改DPI数值，则批量修改DPI，每张图的像素尺寸不变
                if self.dpi_enabled.get() and dpi_str and not modified_width and not modified_height:
                    try:
                        # 直接使用用户输入的DPI值
                        new_dpi = float(dpi_str)
                    except ValueError:
                        pass

                # 2. 若只修改宽/高，按用户输入的宽或高的厘米或英寸数值按原比例各自批量修改
                # 像素尺寸不变，调整DPI
                elif (modified_width or modified_height) and (not dpi_str or not self.dpi_enabled.get()):
                    try:
                        if modified_width:
                            # 用户修改了宽度（厘米或英寸），计算新DPI
                            physical_width = float(modified_width)
                            # 将物理尺寸转换为英寸
                            if current_unit == "cm":
                                physical_width_inch = physical_width / 2.54
                            else:  # current_unit == "inch"
                                physical_width_inch = physical_width
                            # 计算新DPI = 像素宽度 / 物理宽度（英寸）
                            new_dpi = oriented_width / physical_width_inch
                        elif modified_height:
                            # 用户修改了高度（厘米或英寸），计算新DPI
                            physical_height = float(modified_height)
                            # 将物理尺寸转换为英寸
                            if current_unit == "cm":
                                physical_height_inch = physical_height / 2.54
                            else:  # current_unit == "inch"
                                physical_height_inch = physical_height
                            # 计算新DPI = 像素高度 / 物理高度（英寸）
                            new_dpi = oriented_height / physical_height_inch
                    except ValueError:
                        pass

                # 3. 若都修改，按输入的DPI和宽或者高批量原比例计算
                elif self.dpi_enabled.get() and dpi_str and (modified_width or modified_height):
                    try:
                        new_dpi = float(dpi_str)
                        if modified_width:
                            # 按输入的DPI和宽度计算新的像素尺寸
                            physical_width = float(modified_width)
                            target_width = self.convert_to_pixels(physical_width, current_unit, new_dpi)
                            target_height = target_width * aspect_ratio
                            final_width = int(round(target_width))
                            final_height = int(round(target_height))
                        else:
                            # 按输入的DPI和高度计算新的像素尺寸
                            physical_height = float(modified_height)
                            target_height = self.convert_to_pixels(physical_height, current_unit, new_dpi)
                            target_width = target_height / aspect_ratio
                            final_width = int(round(target_width))
                            final_height = int(round(target_height))
                    except ValueError:
                        pass

        # 像素单位的处理
        elif current_unit == "pixel":
            # DPI数值均相同时的处理
            if uniform_dpi:
                if modified_width and not modified_height:
                    # 只修改宽度，保持原比例
                    try:
                        target_width = int(modified_width)
                        target_height = int(round(target_width * aspect_ratio))
                        final_width = target_width
                        final_height = target_height
                    except ValueError:
                        pass
                elif modified_height and not modified_width:
                    # 只修改高度，保持原比例
                    try:
                        target_height = int(modified_height)
                        target_width = int(round(target_height / aspect_ratio))
                        final_width = target_width
                        final_height = target_height
                    except ValueError:
                        pass
                elif self.dpi_enabled.get() and dpi_str:
                    # 只修改DPI，计算新像素尺寸
                    try:
                        new_dpi = float(dpi_str)
                        # 计算原始物理尺寸（英寸）
                        physical_width = oriented_width / float(original_dpi)
                        physical_height = oriented_height / float(original_dpi)
                        # 计算新像素尺寸
                        final_width = int(round(physical_width * new_dpi))
                        final_height = int(round(physical_height * new_dpi))
                    except ValueError:
                        pass
            # DPI数值均不相同时的处理
            else:
                if self.dpi_enabled.get() and dpi_str and not modified_width and not modified_height:
                    # 只修改DPI，保持物理尺寸不变
                    try:
                        new_dpi = float(dpi_str)
                        # 计算原始物理尺寸（英寸）
                        physical_width = oriented_width / float(original_dpi)
                        physical_height = oriented_height / float(original_dpi)
                        # 计算新像素尺寸
                        final_width = int(round(physical_width * new_dpi))
                        final_height = int(round(physical_height * new_dpi))
                    except ValueError:
                        pass
                elif modified_width and not modified_height:
                    # 只修改宽度，使用原图DPI，保持原比例
                    try:
                        target_width = int(modified_width)
                        target_height = int(round(target_width * aspect_ratio))
                        final_width = target_width
                        final_height = target_height
                    except ValueError:
                        pass
                elif modified_height and not modified_width:
                    # 只修改高度，使用原图DPI，保持原比例
                    try:
                        target_height = int(modified_height)
                        target_width = int(round(target_height / aspect_ratio))
                        final_width = target_width
                        final_height = target_height
                    except ValueError:
                        pass
                elif self.dpi_enabled.get() and dpi_str and (modified_width or modified_height):
                    # 修改宽/高和DPI
                    try:
                        new_dpi = float(dpi_str)
                        if modified_width:  # 优先使用宽度
                            target_width = int(modified_width)
                            target_height = int(round(target_width * aspect_ratio))
                        else:  # 使用高度
                            target_height = int(modified_height)
                            target_width = int(round(target_height / aspect_ratio))
                        final_width = target_width
                        final_height = target_height
                    except ValueError:
                        pass

        # 返回计算得到的像素尺寸和DPI
        return final_width, final_height, new_dpi

    pass
